home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / dir / readdir.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  2KB  |  107 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #if defined(LIBC_SCCS) && !defined(lint)
  8. static char sccsid[] = "@(#)readdir.c    5.2 (Berkeley) 3/9/86";
  9. #endif
  10.  
  11. #include <stddef.h>
  12. #include <assert.h>
  13.  
  14. #include <sys/param.h>
  15. #include <sys/dir.h>
  16.  
  17. static long swapLong();
  18. static short swapShort();
  19.  
  20. /*
  21.  * get next entry in a directory.
  22.  */
  23. struct direct *
  24. readdir(dirp)
  25.     register DIR *dirp;
  26. {
  27.     register struct direct *dp;
  28.  
  29.     for (;;) {
  30.     if (dirp->dd_loc == 0) {
  31.         dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
  32.         DIRBLKSIZ);
  33.         if (dirp->dd_size <= 0) {
  34.         return NULL;
  35.         }
  36.     }
  37.     if (dirp->dd_loc >= dirp->dd_size) {
  38.         dirp->dd_loc = 0;
  39.         continue;
  40.     }
  41.     dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
  42.  
  43.     /*
  44.      * Filesystems on big-endian and little-endian systems
  45.      * store the information in the directory in different
  46.      * byte order.  It is kind of tricky to detect which
  47.      * byte order this directory uses.  The record length
  48.      * (d_reclen) must be at least 8 (the offset of d_name
  49.      * in the direct structure) and can not be more than
  50.      * 512 (DIRBLKSIZ).  None of the numbers in the set [8-512]
  51.      * map back onto the same set under byte-swapping, so this
  52.      * is a reliable way of checking.
  53.      */
  54.     if ((unsigned) dp->d_reclen > DIRBLKSIZ ||
  55.         (unsigned) dp->d_reclen < offsetof(struct direct, d_name[0])) {
  56.  
  57.         /*
  58.          * Try byte swapping this entry.
  59.          */
  60.         dp->d_ino = swapLong(dp->d_ino);
  61.         dp->d_reclen = swapShort(dp->d_reclen);
  62.         dp->d_namlen = swapShort(dp->d_namlen);
  63.     }
  64.     if (dp->d_reclen == 0 || dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
  65.         return NULL;
  66.     }
  67.     dirp->dd_loc += dp->d_reclen;
  68.     if (dp->d_ino != 0) {
  69.         assert(dp->d_namlen <= MAXNAMLEN);
  70.         return dp;
  71.     }
  72.     }
  73. }
  74.  
  75. static long
  76. swapLong(x)
  77.     long x;
  78. {        
  79.     union {
  80.     long l;
  81.     char c[4];
  82.     } in, out;
  83.  
  84.     in.l = x;
  85.     out.c[0] = in.c[3];
  86.     out.c[1] = in.c[2];
  87.     out.c[2] = in.c[1];
  88.     out.c[3] = in.c[0];
  89.     return out.l;
  90. }
  91.  
  92. static short
  93. swapShort(x)
  94.     short x;
  95. {
  96.     union {
  97.     short s;
  98.     char c[2];
  99.     } in, out;
  100.  
  101.     in.s = x;
  102.     out.c[0] = in.c[1];
  103.     out.c[1] = in.c[0];
  104.     return out.s;
  105. }
  106.  
  107.